#include "ThreadPool.h"
#include "TaskExecutor.h"

using namespace std;
using namespace threadpool;

void ThreadPool::add(size_t num) {
    lock_guard<mutex> lock(mutex_);
    for (size_t i = 0; i < num; ++i) {
        workers_.emplace_back(&ThreadPool::workThread, this);
    }
}

void ThreadPool::remove(size_t num) {
    for (size_t i = 0; i < std::min(num, workers_.size()); ++i) {
        submitSuicideTask(0, []() {});
    }
}

void ThreadPool::stop() {
    stop_.store(true);
    queue_.stop();
    for (auto &worker: workers_) {
        if (worker.joinable()) {
            worker.join();
        }
    }
    workers_.clear();
}

void ThreadPool::submit(const std::shared_ptr<Task> &task) {
    queue_.push(task);
}

void ThreadPool::workThread() {
    while (!stop_.load()) {
        std::shared_ptr<Task> task = queue_.pop();
        if (task == nullptr) {
            continue;
        }
        work_thread_.fetch_add(1);
        if (task_executor_->defaultBeforeExecute(task, this) == ThreadStatus::ThreadExit) {
            work_thread_.fetch_sub(1);
            break;
        }
        task->execute();
        if (task_executor_->defaultAfterExecute(task, this) == ThreadStatus::ThreadExit) {
            work_thread_.fetch_sub(1);
            break;
        }
        work_thread_.fetch_sub(1);
    }
}